<script setup lang="ts">
import { computed, reactive, ref } from 'vue';
import { ActiveHealthCheckConfig, ClusterConfig, DestinationConfig, ForwarderRequestConfig, HealthCheckConfig, HttpClientConfig, PassiveHealthCheckConfig, SessionAffinityConfig, SessionAffinityCookieConfig, WebProxyConfig } from '../../services/client';
import NtmMetaDataEditor from '../../components/Editors/NtmMetaDataEditor.vue';
import type { FormInstance, FormRules } from 'element-plus';
import Errors from '../../types/Errors';
import MenuItemBox from '../../components/basic/MenuItemBox.vue';
import NtmHealthCheckConfigEditor from '../../components/Editors/NtmHealthCheckConfigEditor.vue';
import ClusterConfigConstants from '../../constants/ClusterConfigConstants';
import NtmSessionAffinityConfigEditor from '../../components/Editors/NtmSessionAffinityConfigEditor.vue';
import NtmForwarderRequestConfigEditor from '../../components/Editors/NtmForwarderRequestConfigEditor.vue';
import NtmDestinationConfigListEditor from '../../components/Editors/NtmDestinationConfigListEditor.vue';

const emits = defineEmits({
    save(value: ClusterConfig) {
        if (!value) {
            return false
        }

        return true
    },
    cancel() {
        return true
    }
})

const props = defineProps<{ data: ClusterConfig, isCreate?: boolean }>();
const { isCreate = false } = props;

const allNames = ['basic', 'loadBalancing', 'sessionAffinity', 'healthCheck', 'httpClient', 'httpRequest', 'destinationConfigs', 'metadata'];
const activeNames = ref<string[]>(allNames);

let config = reactive<ClusterConfig>(props.data);

const formRef = ref<FormInstance>();
const errors = ref<Errors>({});
const destinationErrors = ref<Errors>({});

const disableSessionAffinity = computed(() => {
    return config.sessionAffinity === undefined;
});
const initSessionAffinity = () => {
    config.sessionAffinity = new SessionAffinityConfig();
    config.sessionAffinity.cookie = new SessionAffinityCookieConfig();
}
const removeSessionAffinity = () => {
    config.sessionAffinity = undefined;
}

const disableHealthCheck = computed(() => {
    return config.healthCheck === undefined;
})
const initHealthCheck = () => {
    config.healthCheck = new HealthCheckConfig();
    config.healthCheck.active = new ActiveHealthCheckConfig();
    config.healthCheck.active.policy = "ConsecutiveFailures";
    config.healthCheck.passive = new PassiveHealthCheckConfig();
    config.healthCheck.passive.policy = "TransportFailureRateHealthPolicy";
}
const removeHealthCheck = () => {
    config.healthCheck = undefined;
}

const disableHttpClient = computed(() => {
    return config.httpClient === undefined;
})
const initHttpClient = () => {
    config.httpClient = new HttpClientConfig();
    config.httpClient.webProxy = new WebProxyConfig();
}
const removeHttpClient = () => {
    config.httpClient = undefined
}
const disableHttpRequest = computed(() => {
    return config.httpRequest === undefined;
})
const initHttpRequest = () => {
    config.httpRequest = new ForwarderRequestConfig()
}
const removeHttpRequest = () => {
    config.httpRequest = undefined;
}

const disableDestinations = computed(() => {
    return config.destinationConfigs === undefined;
})
const initDestinatiions = () => {
    config.destinationConfigs = [];
}
const removeDestinations = () => {
    config.destinationConfigs = undefined
}

const disableMetaData = computed(() => {
    return config.metadata === undefined
})
const initMetaData = () => {
    config.metadata = {}
}
const removeMetaData = () => {
    config.metadata = undefined
}

const rules = reactive<FormRules<ClusterConfig>>({
    clusterId: [
        {
            type: 'string', required: true, trigger: 'change', message: '请输入Cluster Id',
        },
        {
            // 正则校验，clusterId只能以字母开头，允许数字，大小写字母，下划线
            validator: (_rule, value, callback, _source, _options) => {
                if (!isCreate) {
                    callback()
                }
                if (/^[a-zA-Z0-9]\w*$/.test(value)) {
                    callback()
                }
                else {
                    callback('只能以字母开头，允许数字，大小写字母，下划线');
                }
            }
        }
    ],
    metadata: [
        {
            validator: (_rule, _value, callback, _source, _options) => {
                const errorkeys = Object.keys(errors.value);
                if (errorkeys.length > 0) {
                    const errorMessage = errorkeys.map(key => {
                        return `键：${key}: ${errors.value[key].join(',')}`
                    }).join(';');
                    callback(errorMessage)
                }
                else {
                    callback();
                }
            },
            trigger: ['change', 'blur']
        }
    ],
    "sessionAffinity.affinityKeyName": [
        {
            validator: (_, value, callback, _source, _options) => {
                if (config.sessionAffinity?.enabled && value && value.length > 0) {
                    callback();
                }
                else {
                    callback("当配置亲和性配置时，必须设置Affinity Key Name")
                }
            }
        }
    ],
    destinationConfigs: [
        {
            validator: (_rule, value: DestinationConfig[], callback, _source, _options) => {
                if (value.length == 0) {
                    callback()
                    return
                }

                const errors = []

                Object.keys(destinationErrors).filter(key => {
                    return destinationErrors.value[key] && destinationErrors.value[key].length > 0
                }).map(key => {
                    return `键：${key}: ${destinationErrors.value[key].join(',')}`
                }).forEach(e => {
                    errors.push(e)
                });

                // empty destination config id
                const emptyDestinationConfigId = value.filter(config => {
                    return !config.destinationConfigId || config.destinationConfigId == ''
                }).map(config => {
                    return config
                });
                if (emptyDestinationConfigId.length > 0) {
                    errors.push(`Destination Config Id必填`)
                }

                // repeat destination config ids
                const configIndex = value.reduce((prev, curr) => {
                    prev = prev || {}
                    prev[curr.destinationConfigId] = prev[curr.destinationConfigId] || []
                    prev[curr.destinationConfigId].push(curr)
                    return prev;
                }, {} as { [key: string]: DestinationConfig[] })

                const repeatIds = Object.keys(configIndex).filter(key => {
                    return configIndex[key].length > 1
                });

                if (repeatIds.length > 0) {
                    errors.push(`Destination Config Id重复: ${repeatIds.join(',')}`)
                }

                // empty address
                const emtpyAddress = value.filter(config => {
                    return !config.address || config.address == ''
                }).map(config => {
                    return config.destinationConfigId
                });

                if (emtpyAddress.length > 0) {
                    errors.push(`Address必填`)
                }

                if (errors.length > 0) {
                    callback(errors.join('; '))
                }
                else {
                    callback()
                }
            }
        }
    ]
})

const expendAll = () => {
    activeNames.value = allNames
}

const save = () => {
    formRef.value?.validate(isValid => {
        if (isValid) {
            emits('save', config);
        }
    })
}

const cancel = () => {
    emits('cancel')
}

</script>

<template>
    <ElContainer style="height: 100%;">
        <ElAside>
            <ElScrollbar>
                <ElMenu default-active="basic">
                    <ElMenuItem index="basic">
                        <ElText>
                            基础设置
                            <el-icon>
                                <Check />
                            </el-icon>
                        </ElText>
                    </ElMenuItem>
                    <ElMenuItem index="loadBalancing">
                        <ElText>
                            负载均衡
                            <el-icon>
                                <Check />
                            </el-icon>
                        </ElText>
                    </ElMenuItem>
                    <ElMenuItem index="sessionAffinity">
                        <template #title>
                            <MenuItemBox label="">
                                <template #default>
                                    <ElText truncated>
                                        会话亲和性
                                        <el-icon v-if="!disableSessionAffinity">
                                            <Check />
                                        </el-icon>
                                    </ElText>
                                </template>
                                <template #right>
                                    <ElButton v-if="disableSessionAffinity" size="small" @click="initSessionAffinity">
                                        添加
                                    </ElButton>
                                    <ElButton v-else size="small" type="danger" @click="removeSessionAffinity">
                                        移除
                                    </ElButton>
                                </template>
                            </MenuItemBox>
                        </template>
                    </ElMenuItem>
                    <ElMenuItem index="healthCheck">
                        <template #title>
                            <MenuItemBox>
                                <template #default>
                                    <ElText truncated>
                                        健康检查
                                        <ElIcon v-if="!disableHealthCheck">
                                            <Check />
                                        </ElIcon>
                                    </ElText>
                                </template>
                                <template #right>
                                    <ElButton v-if="disableHealthCheck" size="small" @click="initHealthCheck">添加</ElButton>
                                    <ElButton v-else size="small" type="danger" @click="removeHealthCheck">移除</ElButton>
                                </template>
                            </MenuItemBox>
                        </template>
                    </ElMenuItem>
                    <ElMenuItem index="httpClient">
                        <template #title>
                            <MenuItemBox>
                                <template #default>
                                    <ElText truncated>
                                        客户端
                                        <ElIcon v-if="!disableHttpClient">
                                            <Check />
                                        </ElIcon>
                                    </ElText>
                                </template>
                                <template #right>
                                    <ElButton v-if="disableHttpClient" size="small" @click="initHttpClient">添加</ElButton>
                                    <ElButton v-else size="small" type="danger" @click="removeHttpClient">移除</ElButton>
                                </template>
                            </MenuItemBox>
                        </template>
                    </ElMenuItem>
                    <ElMenuItem index="httpRequest">
                        <template #title>
                            <MenuItemBox>
                                <template #default>
                                    <ElText truncated>
                                        请求
                                        <ElIcon v-if="!disableHttpRequest">
                                            <Check />
                                        </ElIcon>
                                    </ElText>
                                </template>
                                <template #right>
                                    <ElButton v-if="disableHttpRequest" size="small" @click="initHttpRequest">添加</ElButton>
                                    <ElButton v-else size="small" type="danger" @click="removeHttpRequest">移除</ElButton>
                                </template>
                            </MenuItemBox>
                        </template>
                    </ElMenuItem>
                    <ElMenuItem index="destinationConfigs">
                        <template #title>
                            <MenuItemBox>
                                <template #default>
                                    <ElText truncated>
                                        目标
                                        <ElIcon v-if="!disableDestinations">
                                            <Check />
                                        </ElIcon>
                                    </ElText>
                                </template>
                                <template #right>
                                    <ElButton v-if="disableDestinations" size="small" @click="initDestinatiions">添加
                                    </ElButton>
                                    <ElButton v-else size="small" type="danger" @click="removeDestinations">移除</ElButton>
                                </template>
                            </MenuItemBox>
                        </template>
                    </ElMenuItem>
                    <ElMenuItem index="metadata">
                        <template #title>
                            <MenuItemBox>
                                <template #default>
                                    <ElText truncated>
                                        元数据
                                        <ElIcon v-if="!disableMetaData">
                                            <Check />
                                        </ElIcon>
                                    </ElText>
                                </template>
                                <template #right>
                                    <ElButton v-if="disableMetaData" size="small" @click="initMetaData">添加</ElButton>
                                    <ElButton v-else size="small" type="danger" @click="removeMetaData">移除</ElButton>
                                </template>
                            </MenuItemBox>
                        </template>
                    </ElMenuItem>
                </ElMenu>
            </ElScrollbar>
        </ElAside>
        <ElContainer class="cluster-editor-main">
            <ElHeader>
                <ElButton @click="expendAll()" size="small">全部展开</ElButton>
                <ElButton @click="activeNames = []" size="small">全部折叠</ElButton>
            </ElHeader>

            <ElScrollbar>
                <ElRow>
                    <ElCol :span="24" :style="{ scroll: 'auto' }">
                        <ElForm ref="formRef" :rules="rules" :model="config" label-width="230px" label-position="top"
                            status-icon>
                            <ElCollapse v-model="activeNames">
                                <ElCollapseItem name="basic">
                                    <template #title>
                                        <h1>基础设置</h1>
                                    </template>
                                    <ElFormItem prop="clusterId" label="Cluster Id">
                                        <ElInput :disabled="!isCreate" v-model="config.clusterId"></ElInput>
                                    </ElFormItem>
                                    <ElFormItem prop="clusterName" label="Cluster Name">
                                        <ElInput v-model="config.clusterName"></ElInput>
                                    </ElFormItem>
                                    <ElFormItem prop="description" label="Description">
                                        <ElInput v-model="config.description"></ElInput>
                                    </ElFormItem>
                                </ElCollapseItem>
                                <ElCollapseItem name="loadBalancing">
                                    <template #title>
                                        <h1>负载均衡</h1>
                                    </template>
                                    <ElFormItem prop="loadBalancingPolicy" label="Policy">
                                        <!-- <ElInput clearable v-model="config.loadBalancingPolicy"></ElInput> -->
                                        <ElSelect v-model="config.loadBalancingPolicy" clearable>
                                            <ElOption
                                                v-for="(policy, index) in ClusterConfigConstants.LoadBalancingPolicies"
                                                :key="index" :value="policy">
                                                {{ policy }}
                                            </ElOption>
                                        </ElSelect>
                                    </ElFormItem>
                                </ElCollapseItem>
                                <ElCollapseItem name="sessionAffinity" v-if="!disableSessionAffinity">
                                    <template #title>
                                        <h1>会话亲和性</h1>
                                    </template>
                                    <NtmSessionAffinityConfigEditor v-model="config.sessionAffinity"
                                        prop-name-prefix="sessionAffinity"></NtmSessionAffinityConfigEditor>
                                </ElCollapseItem>
                                <ElCollapseItem name="healthCheck" v-if="!disableHealthCheck">
                                    <template #title>
                                        <h1>健康检查</h1>
                                    </template>
                                    <NtmHealthCheckConfigEditor v-model="config.healthCheck"
                                        prop-name-prefix="healthConfig"></NtmHealthCheckConfigEditor>
                                </ElCollapseItem>
                                <ElCollapseItem name="httpClient" v-if="!disableHttpClient">
                                    <template #title>
                                        <h1>客户端</h1>
                                    </template>
                                    <NtmHttpClientConfigEditor v-model="config.httpClient"></NtmHttpClientConfigEditor>
                                </ElCollapseItem>
                                <ElCollapseItem name="httpRequest" v-if="!disableHttpRequest">
                                    <template #title>
                                        <h1>请求</h1>
                                    </template>
                                    <NtmForwarderRequestConfigEditor v-model="config.httpRequest">
                                    </NtmForwarderRequestConfigEditor>
                                </ElCollapseItem>
                                <ElCollapseItem name="destinationConfigs" v-if="!disableDestinations">
                                    <template #title>
                                        <h1>目标</h1>
                                    </template>
                                    <ElFormItem prop="destinationConfigs">
                                        <NtmDestinationConfigListEditor v-model="config.destinationConfigs"
                                            v-model:errors="destinationErrors">
                                        </NtmDestinationConfigListEditor>
                                    </ElFormItem>
                                </ElCollapseItem>
                                <ElCollapseItem name="metadata" v-if="!disableMetaData">
                                    <template #title>
                                        <h1>元数据</h1>
                                    </template>
                                    <ElFormItem prop="metadata">
                                        <NtmMetaDataEditor v-model="config.metadata" v-model:errors="errors">
                                        </NtmMetaDataEditor>
                                    </ElFormItem>
                                </ElCollapseItem>
                            </ElCollapse>
                        </ElForm>
                    </ElCol>
                </ElRow>
            </ElScrollbar>

            <ElFooter>
                <ElRow style="margin-top: 10px;">
                    <ElCol>
                        <ElButton type="primary" @click="save">保存</ElButton>
                        <ElButton @click="cancel">取消</ElButton>
                    </ElCol>
                </ElRow>
            </ElFooter>
        </ElContainer>
    </ElContainer>
</template>

<style scoped>
.el-form {
    padding-left: 12px;
}

h1 {
    font-size: 24px;
}

.cluster-editor-main {
    border-left: solid 1px var(--el-menu-border-color);
}

:global(.el-form-item__label) {
    font-weight: 600;
}
</style>